<template>
  <div class="base-form">
    <div class="header">
      <slot name="header"></slot>
    </div>
    <el-form
      :label-width="labelWidth"
      :model="modelValue"
      :rules="fromRules"
      ref="ruleFormRef"
    >
      <el-row>
        <template v-for="item in formItems" :key="item.label">
          <el-col v-bind="item.colLayout || colLayout" ref="formItemRef">
            <el-form-item
              v-if="!item.isHidden"
              :label="item.label"
              :style="itemStyle"
              :label-width="item.labelWidth"
              v-bind="item.otherOptions"
              :prop="item.field"
            >
              <!-- 输入框 -->
              <template
                v-if="item.type === 'input' || item.type === 'password'"
              >
                <el-input
                  :placeholder="item.placeholder"
                  :show-password="item.type === 'password'"
                  v-bind="item.childrenProps"
                  :model-value="modelValue[`${item.field}`]"
                  @update:modelValue="handleValuechange($event, item.field)"
                />
              </template>
              <!-- 下拉框 -->
              <template v-else-if="item.type === 'select'">
                <el-select
                  :placeholder="item.placeholder"
                  style="width: 100%"
                  :model-value="modelValue[`${item.field}`]"
                  @update:modelValue="handleValuechange($event, item.field)"
                >
                  <el-option
                    v-for="option in item.options"
                    :key="option.value"
                    :label="option.label"
                    :value="option.value"
                  >
                  </el-option>
                </el-select>
              </template>
              <!-- 日期选择 -->
              <template v-else-if="item.type === 'datepicker'">
                <el-date-picker
                  style="width: 100%"
                  v-bind="item.childrenProps"
                  :model-value="modelValue[`${item.field}`]"
                  @update:modelValue="handleValuechange($event, item.field)"
                ></el-date-picker>
              </template>
              <!-- 开关 -->
              <template v-else-if="item.type === 'switch'">
                <el-switch
                  :model-value="modelValue[`${item.field}`]"
                  @update:modelValue="handleValuechange($event, item.field)"
                />
              </template>
              <!-- 多选 -->
              <template v-else-if="item.type === 'checkbox'">
                <el-checkbox-group
                  :model-value="modelValue[`${item.field}`]"
                  @update:modelValue="handleValuechange($event, item.field)"
                >
                  <el-checkbox
                    v-for="i in item.options"
                    :key="i.value"
                    :value="i.value"
                    :label="i.label"
                  >
                  </el-checkbox>
                </el-checkbox-group>
              </template>
              <!-- 单选 -->
              <template v-else-if="item.type === 'radio'">
                <el-radio-group
                  :model-value="modelValue[`${item.field}`]"
                  @update:modelValue="handleValuechange($event, item.field)"
                >
                  <el-radio
                    v-for="i in item.options"
                    :key="i.value"
                    :label="i.value"
                  >
                    {{ i.label }}
                  </el-radio>
                </el-radio-group>
              </template>
              <!-- 数字框 -->
              <template v-else-if="item.type === 'inputNumber'">
                <el-input-number
                  :min="item.min"
                  :max="item.max"
                  v-bind="item.childrenProps"
                  :model-value="modelValue[`${item.field}`]"
                  @update:modelValue="handleValuechange($event, item.field)"
                />
              </template>
              <template v-else-if="item.type === 'rate'">
                <el-rate
                  :model-value="modelValue[`${item.field}`]"
                  @update:modelValue="handleValuechange($event, item.field)"
                />
              </template>
              <!-- 树形选择 -->
              <template v-else-if="item.type === 'treeSelect'">
                <el-tree-select
                  :data="item.options"
                  v-bind="item.childrenProps"
                  style="width: 240px"
                  :model-value="modelValue[`${item.field}`]"
                  @update:modelValue="handleValuechange($event, item.field)"
                />
              </template>
              <!-- 上传 -->
              <template v-else-if="item.type === 'upload'">
                <el-upload
                  v-if="!item.slotName"
                  class="upload-demo"
                  drag
                  v-bind="item.childrenProps"
                  :on-exceed="handleExceed"
                  :model-value="modelValue[`${item.field}`]"
                  @update:modelValue="
                    handleValuechange($event, item.field, 'upload')
                  "
                >
                  <el-icon class="el-icon--upload">
                    <component :is="item.childrenProps?.icon" />
                  </el-icon>
                  <div class="el-upload__text">
                    {{
                      item.childrenProps?.tips === null
                        ? ""
                        : item.childrenProps?.tips
                        ? item.childrenProps?.tips
                        : "可支持拖拽"
                    }}
                  </div>
                  <template #tip>
                    <div class="el-upload__tip">
                      {{
                        item.childrenProps?.limitationText
                          ? item.childrenProps?.limitationText
                          : ""
                      }}
                    </div>
                  </template>
                </el-upload>
                <slot v-else :name="item.slotName"> </slot>
              </template>
            </el-form-item>
          </el-col>
        </template>
      </el-row>
    </el-form>
    <div class="footer">
      <slot name="footer"></slot>
    </div>
  </div>
</template>

<script setup lang="ts">
import { nextTick, onMounted, ref, defineExpose, type PropType } from "vue";
import type { IFormItem } from "./types";
import eventBus from "/@/global/event-bus";

const props = defineProps({
  // 表单项
  formItems: {
    type: Array as PropType<IFormItem[]>,
    default: () => []
  },
  // label宽度
  labelWidth: {
    type: String,
    default: "100px"
  },
  // 表单校验规则
  rules: {
    type: Object,
    default: () => {}
  },
  // 表单项样式
  itemStyle: {
    type: Object,
    default: () => ({ padding: "10px 20px" })
  },
  // 自适应布局
  colLayout: {
    type: Object,
    default: () => ({
      xs: 24,
      sm: 24,
      md: 12,
      lg: 8,
      xl: 6 //>1920 4个
    })
  },
  // 表单数据
  modelValue: {
    type: Object,
    required: true
  },
  // 是否超出隐藏,用于获取表单项高度
  isOver: {
    type: Boolean,
    default: false
  }
});

// 表单实例
const ruleFormRef = ref<any>();
const fromRules = ref<any>(props.rules ?? {});

// 上传文件列表
const fileList = ref<Array<any>>([]);
const handleExceed = files => {
  fileList.value = files;
};

const emit = defineEmits(["update:modelValue"]);
// 输入框值变化修改父组件的值
const handleValuechange = (value: any, field: string, type?: string) => {
  let data = { ...props.modelValue, [field]: value };
  if (type === "upload") {
    data = { ...props.modelValue, [field]: fileList.value };
  }
  emit("update:modelValue", data);
};

// 获取表单项的的高度
const formItemRef = ref<Array<any>>([]);
onMounted(() => {
  nextTick(() => {
    if (formItemRef.value.length && props.isOver) {
      const columnElement = formItemRef.value[0]?.$el; // 获取 el-col 的根 DOM 元素
      const height = columnElement.offsetHeight; // 获取高度
      eventBus.colHeight = height;
    }
  });
});

defineExpose({
  ruleFormRef
});
</script>

<style lang="scss" scoped>
.base-form {
  background: white;
}
</style>
